#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
//over
int n, m, l, v, t, pos[MAXN], d[MAXN], v0[MAXN], a[MAXN], ans1, ans2;
bool vis[MAXN];

struct node{
    int cnt, id;
    vector<int> note;
}can[MAXN];

bool cmp(node a, node b){
    if(a.cnt == b.cnt) return a.id > b.id;
    else return a.cnt > b.cnt;
}

int search(int x){
    int left = 1, right = m + 1, mid;
    while(left < right - 1){
        mid = (left + right) / 2;
        if(pos[mid] >= x){
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return right;
}


int main() {
    freopen("detect.in", "r", stdin);
    freopen("detect.out", "w", stdout);
    scanf("%d", &t);
    while(t--){
        scanf("%d%d%d%d", &n, &m, &l, &v);
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d", &d[i], &v0[i], &a[i]);
        }
        for(int i = 1; i <= m; i++){
            scanf("%d", &pos[i]);
        }
        //io
        for(int i = 1; i <= n; i++){
            if(a[i] == 0){
                if(v0[i] > v){
                    int f = search(d[i]);
                    if(f != m + 1){
                        ans1++;
                        for(int j = f; j <= m; j++){
                            can[j].note.push_back(i);
                            can[j].cnt++;
                        }

                    }
                }
            } else {
                double dist = (v * v * 1.0 - v0[i] * v0[i] * 1.0) / (2.0 * a[i]);
                if(a[i] > 0){
                    int f_dis = int(dist) + 1;
                    int f = search(d[i] + f_dis);
                    if(f != m + 1){
                        ans1++;
                        for(int j = f; j <= m; j++){
                            can[j].note.push_back(i);
                            can[j].cnt++;
                        }
                    }
                } else {
                    if(v0[i] > v) {
                        int f_dis = int(dist);
                        if(dist - f_dis < 1) f_dis--;
                        int f_s = search(d[i]);
                        int f_e = search(d[i] + f_dis);
                        if(f_e == m + 1) f_e = m;
                        if(f_s != m + 1 && f_s != f_e){
                            ans1++;
                            for(int j = f_s; j <= f_e; j++){
                                can[j].note.push_back(i);
                                can[j].cnt++;
                            }
                        }
                    }
                }
            }
        }
        //detect
        sort(can + 1, can + 1 + m, cmp);
        int cnt = 0;
        for(int i = 1; i <= m; i++){
            if(cnt == n) break;
            bool flag = false;
            for(auto j : can[i].note){
                if(!vis[j]){
                    flag = true;
                    vis[j] = true;
                    cnt++;
                }
            }
            if(flag) ans2++;
        }
        //close
        cout << ans1 << " " << m - ans2 << endl;
        ans1 = 0;
        ans2 = 0;
        memset(vis, false, sizeof(vis));
        for(int i = 1; i <= m; i++){
            can[i].id = i;
            can[i].cnt = 0;
            can[i].note.clear();
        }
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}
